#include "StbImage.hpp"
#include <iostream>
#include <vector>
#include <Eigen/Eigen>
using namespace std;

using vec2 = Eigen::Vector2f;
using vec3 = Eigen::Vector3f;

vector<vec3> triangle1 = {
    vec3{0.2, 0.25, 1},vec3{0.8, 0.5, 1},vec3{0.5, 0.75, 1}
};

vector<vec3> triangle2 = {
    vec3{0.1, 0.4, 1},vec3{0.6, 0.15, 1},vec3{0.3, 0.75, 1}
};

bool isInTriangle(int x, int y, vector<Eigen::Vector3i>& tri) {
    Eigen::Vector2i v1, v2;
    for (int i = 0; i < 3; ++i) {
        v1 << tri[(i + 1) % 3][0] - tri[i][0], tri[(i + 1) % 3][1] - tri[i][1];
        v2 << x - tri[i][0], y - tri[i][1];
        if (v2[0] * v1[1] - v2[1] * v1[0] > 0) {
            return false;
        }
    }
    return true;
}

void drawTriangle(StbImage& frame, vector<vec3>& tri, vec3& color) {
    int l, r, b, t;
    int w = frame.w(), h = frame.h();
    vector<Eigen::Vector3i> itri(3);
    for (int i = 0; i < 3; ++i) {
        itri[i] << tri[i][0] * w, tri[i][1] * h, 1000 * tri[i][2];
    }
    l = min(itri[0][0], min(itri[1][0], itri[2][0]));
    r = max(itri[0][0], max(itri[1][0], itri[2][0]));
    b = min(itri[0][1], min(itri[1][1], itri[2][1]));
    t = max(itri[0][1], max(itri[1][1], itri[2][1]));

    Eigen::Vector3i icolor;
    icolor << color[0] * 255, color[1] * 255, color[2] * 255;
    for (int i = l; i <= r; ++i) {
        for (int j = b; j <= t; ++j) {
            if (isInTriangle(i, j, itri)) {
                frame.setColor(i, j, icolor);
            }
        }
    }
}

int main(int argc, char const* argv[]) {
    StbImage frame(500, 400, 3);

    vec3 color(3);
    color << 0.5, 0.2, 0.7;
    drawTriangle(frame, triangle1, color);
    color << 0.8, 0.2, 0.5;
    drawTriangle(frame, triangle2, color);

    frame.write("./res/01out.png");

    return 0;
}
